package sonyflake

import (
	"errors"
	"fmt"
	"net"
	"strconv"
	"sync"

	"github.com/sony/sonyflake"
)

var (
	flake *sonyflake.Sonyflake
	once  sync.Once
)

// getMachineID 从网络接口的MAC地址生成一个机器ID。
func getMachineID() (uint16, error) {
	interfaces, err := net.Interfaces()
	if err != nil {
		return 0, err
	}

	for _, i := range interfaces {
		// 我们寻找一个已启动、非环回且具有MAC地址的接口。
		if i.Flags&net.FlagUp != 0 && i.Flags&net.FlagLoopback == 0 && len(i.HardwareAddr) > 0 {
			// 使用MAC地址的最后两个字节作为机器ID。
			// 这种策略在大多数情况下是有效的，但不能绝对保证唯一性。
			return uint16(i.HardwareAddr[len(i.HardwareAddr)-2])<<8 | uint16(i.HardwareAddr[len(i.HardwareAddr)-1]), nil
		}
	}

	// 如果没有找到合适的网络接口，则返回错误。
	return 0, errors.New("no suitable network interface found to generate machine id")
}

func GetFlake() *sonyflake.Sonyflake {
	once.Do(func() {
		machineID, err := getMachineID()
		if err != nil {
			panic(fmt.Errorf("failed to initialize sonyflake: %w", err))
		}

		settings := sonyflake.Settings{
			MachineID: func() (uint16, error) {
				return machineID, nil
			},
		}
		flake = sonyflake.NewSonyflake(settings)
		if flake == nil {
			panic("failed to create sonyflake instance, machineId might be invalid")
		}
	})

	return flake
}

func GetUint64Flake() uint64 {
	flake := GetFlake()
	id, err := flake.NextID()
	if err != nil {
		panic(err)
	}
	return id
}

func GetIntFlake() int {
	flake := GetFlake()
	id, err := flake.NextID()
	if err != nil {
		panic(err)
	}
	return int(id)
}

func GetStringFlake() string {
	flake := GetFlake()
	id, err := flake.NextID()
	if err != nil {
		panic(err)
	}
	return strconv.Itoa(int(id))
}
